home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-10-28 | 50.8 KB | 1,453 lines |
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- NNNNAAAAMMMMEEEE
- overload - Package for overloading perl operations
-
- SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
- package SomeThing;
-
- use overload
- '+' => \&myadd,
- '-' => \&mysub;
- # etc
- ...
-
- package main;
- $a = new SomeThing 57;
- $b=5+$a;
- ...
- if (overload::Overloaded $b) {...}
- ...
- $strval = overload::StrVal $b;
-
-
- CCCCAAAAVVVVEEEEAAAATTTT SSSSCCCCRRRRIIIIPPPPTTTTOOOORRRR
- Overloading of operators is a subject not to be taken
- lightly. Neither its precise implementation, syntax, nor
- semantics are 100% endorsed by Larry Wall. So any of these
- may be changed at some point in the future.
-
- DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
- DDDDeeeeccccllllaaaarrrraaaattttiiiioooonnnn ooooffff oooovvvveeeerrrrllllooooaaaaddddeeeedddd ffffuuuunnnnccccttttiiiioooonnnnssss
-
- The compilation directive
-
- package Number;
- use overload
- "+" => \&add,
- "*=" => "muas";
-
- declares function _N_u_m_b_e_r::_a_d_d() for addition, and method
- _m_u_a_s() in the "class" Number (or one of its base classes)
- for the assignment form *= of multiplication.
-
- Arguments of this directive come in (key, value) pairs.
- Legal values are values legal inside a &{ ... } call, so the
- name of a subroutine, a reference to a subroutine, or an
- anonymous subroutine will all work. Note that values
- specified as strings are interpreted as methods, not
- subroutines. Legal keys are listed below.
-
- The subroutine add will be called to execute $a+$b if $a is
- a reference to an object blessed into the package Number, or
- if $a is not an object from a package with defined
- mathemagic addition, but $b is a reference to a Number. It
-
-
-
- Page 1 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- can also be called in other situations, like $a+=7, or $a++.
- See the section on _M_A_G_I_C _A_U_T_O_G_E_N_E_R_A_T_I_O_N. (Mathemagical
- methods refer to methods triggered by an overloaded
- mathematical operator.)
-
- Since overloading respects inheritance via the @ISA
- hierarchy, the above declaration would also trigger
- overloading of + and *= in all the packages which inherit
- from Number.
-
- CCCCaaaalllllllliiiinnnngggg CCCCoooonnnnvvvveeeennnnttttiiiioooonnnnssss ffffoooorrrr BBBBiiiinnnnaaaarrrryyyy OOOOppppeeeerrrraaaattttiiiioooonnnnssss
-
- The functions specified in the use overload ... directive
- are called with three (in one particular case with four, see
- the section on _L_a_s_t _R_e_s_o_r_t) arguments. If the corresponding
- operation is binary, then the first two arguments are the
- two arguments of the operation. However, due to general
- object calling conventions, the first argument should always
- be an object in the package, so in the situation of 7+$a,
- the order of the arguments is interchanged. It probably
- does not matter when implementing the addition method, but
- whether the arguments are reversed is vital to the
- subtraction method. The method can query this information
- by examining the third argument, which can take three
- different values:
-
- FALSE the order of arguments is as in the current
- operation.
-
- TRUE the arguments are reversed.
-
- undef the current operation is an assignment variant (as in
- $a+=7), but the usual function is called instead.
- This additional information can be used to generate
- some optimizations. Compare the section on _C_a_l_l_i_n_g
- _C_o_n_v_e_n_t_i_o_n_s _f_o_r _M_u_t_a_t_o_r_s.
-
- CCCCaaaalllllllliiiinnnngggg CCCCoooonnnnvvvveeeennnnttttiiiioooonnnnssss ffffoooorrrr UUUUnnnnaaaarrrryyyy OOOOppppeeeerrrraaaattttiiiioooonnnnssss
-
- Unary operation are considered binary operations with the
- second argument being undef. Thus the functions that
- overloads {"++"} is called with arguments ($a,undef,'') when
- $a++ is executed.
-
- CCCCaaaalllllllliiiinnnngggg CCCCoooonnnnvvvveeeennnnttttiiiioooonnnnssss ffffoooorrrr MMMMuuuuttttaaaattttoooorrrrssss
-
- Two types of mutators have different calling conventions:
-
- ++ and --
- The routines which implement these operators are
- expected to actually _m_u_t_a_t_e their arguments. So,
- assuming that $obj is a reference to a number,
-
-
-
- Page 2 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- sub incr { my $n = $ {$_[0]}; ++$n; $_[0] = bless \$n}
-
- is an appropriate implementation of overloaded ++.
- Note that
-
- sub incr { ++$ {$_[0]} ; shift }
-
- is OK if used with preincrement and with postincrement.
- (In the case of postincrement a copying will be
- performed, see the section on _C_o_p_y _C_o_n_s_t_r_u_c_t_o_r.)
-
- x= and other assignment versions
- There is nothing special about these methods. They may
- change the value of their arguments, and may leave it
- as is. The result is going to be assigned to the value
- in the left-hand-side if different from this value.
-
- This allows for the same method to be used as
- averloaded += and +. Note that this is _a_l_l_o_w_e_d, but
- not recommended, since by the semantic of the section
- on _F_a_l_l_b_a_c_k Perl will call the method for + anyway, if
- += is not overloaded.
-
- WWWWaaaarrrrnnnniiiinnnngggg.... Due to the presense of assignment versions of
- operations, routines which may be called in assignment
- context may create self-referencial structures. Currently
- Perl will not free self-referential structures until cycles
- are explicitly broken. You may get problems when traversing
- your structures too.
-
- Say,
-
- use overload '+' => sub { bless [ \$_[0], \$_[1] ] };
-
- is asking for trouble, since for code $obj += $foo the
- subroutine is called as $obj = add($obj, $foo, undef), or
- $obj = [\$obj, \$foo]. If using such a subroutine is an
- important optimization, one can overload += explicitly by a
- non-"optimized" version, or switch to non-optimized version
- if not defined $_[2] (see the section on _C_a_l_l_i_n_g _C_o_n_v_e_n_t_i_o_n_s
- _f_o_r _B_i_n_a_r_y _O_p_e_r_a_t_i_o_n_s).
-
- Even if no _e_x_p_l_i_c_i_t assignment-variants of operators are
- present in the script, they may be generated by the
- optimizer. Say, ",$obj," or ',' . $obj . ',' may be both
- optimized to
-
- my $tmp = ',' . $obj; $tmp .= ',';
-
-
-
-
-
-
-
- Page 3 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- OOOOvvvveeeerrrrllllooooaaaaddddaaaabbbblllleeee OOOOppppeeeerrrraaaattttiiiioooonnnnssss
-
- The following symbols can be specified in use overload
- directive:
-
- +o _A_r_i_t_h_m_e_t_i_c _o_p_e_r_a_t_i_o_n_s
-
- "+", "+=", "-", "-=", "*", "*=", "/", "/=", "%", "%=",
- "**", "**=", "<<", "<<=", ">>", ">>=", "x", "x=", ".", ".=",
-
- For these operations a substituted non-assignment
- variant can be called if the assignment variant is not
- available. Methods for operations "+", "-", "+=", and
- "-=" can be called to automatically generate increment
- and decrement methods. The operation "-" can be used
- to autogenerate missing methods for unary minus or abs.
-
- See the section on _M_A_G_I_C _A_U_T_O_G_E_N_E_R_A_T_I_O_N, the section on
- _C_a_l_l_i_n_g _C_o_n_v_e_n_t_i_o_n_s _f_o_r _M_u_t_a_t_o_r_s and the section on
- _C_a_l_l_i_n_g _C_o_n_v_e_n_t_i_o_n_s _f_o_r _B_i_n_a_r_y _O_p_e_r_a_t_i_o_n_s) for details
- of these substitutions.
-
- +o _C_o_m_p_a_r_i_s_o_n _o_p_e_r_a_t_i_o_n_s
-
- "<", "<=", ">", ">=", "==", "!=", "<=>",
- "lt", "le", "gt", "ge", "eq", "ne", "cmp",
-
- If the corresponding "spaceship" variant is available,
- it can be used to substitute for the missing operation.
- During sorting arrays, cmp is used to compare values
- subject to use overload.
-
- +o _B_i_t _o_p_e_r_a_t_i_o_n_s
-
- "&", "^", "|", "neg", "!", "~",
-
- "neg" stands for unary minus. If the method for neg is
- not specified, it can be autogenerated using the method
- for subtraction. If the method for "!" is not
- specified, it can be autogenerated using the methods
- for "bool", or "\"\"", or "0+".
-
- +o _I_n_c_r_e_m_e_n_t _a_n_d _d_e_c_r_e_m_e_n_t
-
- "++", "--",
-
- If undefined, addition and subtraction methods can be
- used instead. These operations are called both in
- prefix and postfix form.
-
- +o _T_r_a_n_s_c_e_n_d_e_n_t_a_l _f_u_n_c_t_i_o_n_s
-
-
-
-
- Page 4 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- "atan2", "cos", "sin", "exp", "abs", "log", "sqrt",
-
- If abs is unavailable, it can be autogenerated using
- methods for "<" or "<=>" combined with either unary
- minus or subtraction.
-
- +o _B_o_o_l_e_a_n, _s_t_r_i_n_g _a_n_d _n_u_m_e_r_i_c _c_o_n_v_e_r_s_i_o_n
-
- "bool", "\"\"", "0+",
-
- If one or two of these operations are unavailable, the
- remaining ones can be used instead. bool is used in
- the flow control operators (like while) and for the
- ternary "?:" operation. These functions can return any
- arbitrary Perl value. If the corresponding operation
- for this value is overloaded too, that operation will
- be called again with this value.
-
- +o _S_p_e_c_i_a_l
-
- "nomethod", "fallback", "=",
-
- see the section on _S_P_E_C_I_A_L _S_Y_M_B_O_L_S _F_O_R _u_s_e _o_v_e_r_l_o_a_d.
-
- See the section on _F_a_l_l_b_a_c_k for an explanation of when a
- missing method can be autogenerated.
-
- A computer-readable form of the above table is available in
- the hash %overload::ops, with values being space-separated
- lists of names:
-
- with_assign => '+ - * / % ** << >> x .',
- assign => '+= -= *= /= %= **= <<= >>= x= .=',
- str_comparison => '< <= > >= == !=',
- '3way_comparison'=> '<=> cmp',
- num_comparison => 'lt le gt ge eq ne',
- binary => '& | ^',
- unary => 'neg ! ~',
- mutators => '++ --',
- func => 'atan2 cos sin exp abs log sqrt',
- conversion => 'bool "" 0+',
- special => 'nomethod fallback ='
-
-
- IIIInnnnhhhheeeerrrriiiittttaaaannnncccceeee aaaannnndddd oooovvvveeeerrrrllllooooaaaaddddiiiinnnngggg
-
- Inheritance interacts with overloading in two ways.
-
- Strings as values of use overload directive
- If value in
-
- use overload key => value;
-
-
-
- Page 5 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- is a string, it is interpreted as a method name.
-
- Overloading of an operation is inherited by derived classes
- Any class derived from an overloaded class is also
- overloaded. The set of overloaded methods is the union
- of overloaded methods of all the ancestors. If some
- method is overloaded in several ancestor, then which
- description will be used is decided by the usual
- inheritance rules:
-
- If A inherits from B and C (in this order), B overloads
- + with \&D::plus_sub, and C overloads + by "plus_meth",
- then the subroutine D::plus_sub will be called to
- implement operation + for an object in package A.
-
- Note that since the value of the fallback key is not a
- subroutine, its inheritance is not governed by the above
- rules. In the current implementation, the value of fallback
- in the first overloaded ancestor is used, but this is
- accidental and subject to change.
-
- SSSSPPPPEEEECCCCIIIIAAAALLLL SSSSYYYYMMMMBBBBOOOOLLLLSSSS FFFFOOOORRRR uuuusssseeee oooovvvveeeerrrrllllooooaaaadddd
- Three keys are recognized by Perl that are not covered by
- the above description.
-
- LLLLaaaasssstttt RRRReeeessssoooorrrrtttt
-
- "nomethod" should be followed by a reference to a function
- of four parameters. If defined, it is called when the
- overloading mechanism cannot find a method for some
- operation. The first three arguments of this function
- coincide with the arguments for the corresponding method if
- it were found, the fourth argument is the symbol
- corresponding to the missing method. If several methods are
- tried, the last one is used. Say, 1-$a can be equivalent to
-
- &nomethodMethod($a,1,1,"-")
-
- if the pair "nomethod" => "nomethodMethod" was specified in
- the use overload directive.
-
- If some operation cannot be resolved, and there is no
- function assigned to "nomethod", then an exception will be
- raised via _d_i_e()-- unless "fallback" was specified as a key
- in use overload directive.
-
- FFFFaaaallllllllbbbbaaaacccckkkk
-
- The key "fallback" governs what to do if a method for a
- particular operation is not found. Three different cases
- are possible depending on the value of "fallback":
-
-
-
-
- Page 6 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- +o undef Perl tries to use a substituted method (see
- the section on _M_A_G_I_C _A_U_T_O_G_E_N_E_R_A_T_I_O_N). If
- this fails, it then tries to calls
- "nomethod" value; if missing, an exception
- will be raised.
-
- +o TRUE The same as for the undef value, but no
- exception is raised. Instead, it silently
- reverts to what it would have done were
- there no use overload present.
-
- +o defined, but FALSE
- No autogeneration is tried. Perl tries to
- call "nomethod" value, and if this is
- missing, raises an exception.
-
- NNNNooootttteeee.... "fallback" inheritance via @ISA is not carved in stone
- yet, see the section on _I_n_h_e_r_i_t_a_n_c_e _a_n_d _o_v_e_r_l_o_a_d_i_n_g.
-
- CCCCooooppppyyyy CCCCoooonnnnssssttttrrrruuuuccccttttoooorrrr
-
- The value for "=" is a reference to a function with three
- arguments, i.e., it looks like the other values in use
- overload. However, it does not overload the Perl assignment
- operator. This would go against Camel hair.
-
- This operation is called in the situations when a mutator is
- applied to a reference that shares its object with some
- other reference, such as
-
- $a=$b;
- ++$a;
-
- To make this change $a and not change $b, a copy of $$a is
- made, and $a is assigned a reference to this new object.
- This operation is done during execution of the ++$a, and not
- during the assignment, (so before the increment $$a
- coincides with $$b). This is only done if ++ is expressed
- via a method for '++' or '+=' (or nomethod). Note that if
- this operation is expressed via '+' a nonmutator, i.e., as
- in
-
- $a=$b;
- $a=$a+1;
-
- then $a does not reference a new copy of $$a, since $$a does
- not appear as lvalue when the above code is executed.
-
- If the copy constructor is required during the execution of
- some mutator, but a method for '=' was not specified, it can
- be autogenerated as a string copy if the object is a plain
- scalar.
-
-
-
- Page 7 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- EEEExxxxaaaammmmpppplllleeee
- The actually executed code for
-
- $a=$b;
- Something else which does not modify $a or $b....
- ++$a;
-
- may be
-
- $a=$b;
- Something else which does not modify $a or $b....
- $a = $a->clone(undef,"");
- $a->incr(undef,"");
-
- if $b was mathemagical, and '++' was overloaded with
- \&incr, '=' was overloaded with \&clone.
-
- Same behaviour is triggered by $b = $a++, which is consider
- a synonim for $b = $a; ++$a.
-
- MMMMAAAAGGGGIIIICCCC AAAAUUUUTTTTOOOOGGGGEEEENNNNEEEERRRRAAAATTTTIIIIOOOONNNN
- If a method for an operation is not found, and the value for
- "fallback" is TRUE or undefined, Perl tries to autogenerate
- a substitute method for the missing operation based on the
- defined operations. Autogenerated method substitutions are
- possible for the following operations:
-
- _A_s_s_i_g_n_m_e_n_t _f_o_r_m_s _o_f _a_r_i_t_h_m_e_t_i_c _o_p_e_r_a_t_i_o_n_s
- $a+=$b can use the method for "+" if the
- method for "+=" is not defined.
-
- _C_o_n_v_e_r_s_i_o_n _o_p_e_r_a_t_i_o_n_s
- String, numeric, and boolean conversion are
- calculated in terms of one another if not
- all of them are defined.
-
- _I_n_c_r_e_m_e_n_t _a_n_d _d_e_c_r_e_m_e_n_t
- The ++$a operation can be expressed in terms
- of $a+=1 or $a+1, and $a-- in terms of $a-=1
- and $a-1.
-
- abs($a) can be expressed in terms of $a<0 and -$a
- (or 0-$a).
-
- _U_n_a_r_y _m_i_n_u_s can be expressed in terms of subtraction.
-
- _N_e_g_a_t_i_o_n ! and not can be expressed in terms of
- boolean conversion, or string or numerical
- conversion.
-
- _C_o_n_c_a_t_e_n_a_t_i_o_n can be expressed in terms of string
- conversion.
-
-
-
- Page 8 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- _C_o_m_p_a_r_i_s_o_n _o_p_e_r_a_t_i_o_n_s
- can be expressed in terms of its "spaceship"
- counterpart: either <=> or cmp:
-
- <, >, <=, >=, ==, != in terms of <=>
- lt, gt, le, ge, eq, ne in terms of cmp
-
-
- _C_o_p_y _o_p_e_r_a_t_o_r can be expressed in terms of an assignment
- to the dereferenced value, if this value is
- a scalar and not a reference.
-
- LLLLoooossssiiiinnnngggg oooovvvveeeerrrrllllooooaaaaddddiiiinnnngggg
- The restriction for the comparison operation is that even
- if, for example, `cmp' should return a blessed reference,
- the autogenerated `lt' function will produce only a standard
- logical value based on the numerical value of the result of
- `cmp'. In particular, a working numeric conversion is
- needed in this case (possibly expressed in terms of other
- conversions).
-
- Similarly, .= and x= operators lose their mathemagical
- properties if the string conversion substitution is applied.
-
- When you _c_h_o_p() a mathemagical object it is promoted to a
- string and its mathemagical properties are lost. The same
- can happen with other operations as well.
-
- RRRRuuuunnnn----ttttiiiimmmmeeee OOOOvvvveeeerrrrllllooooaaaaddddiiiinnnngggg
- Since all use directives are executed at compile-time, the
- only way to change overloading during run-time is to
-
- eval 'use overload "+" => \&addmethod';
-
- You can also use
-
- eval 'no overload "+", "--", "<="';
-
- though the use of these constructs during run-time is
- questionable.
-
- PPPPuuuubbbblllliiiicccc ffffuuuunnnnccccttttiiiioooonnnnssss
- Package overload.pm provides the following public functions:
-
- overload::StrVal(arg)
- Gives string value of arg as in absence of stringify
- overloading.
-
- overload::Overloaded(arg)
- Returns true if arg is subject to overloading of some
- operations.
-
-
-
-
- Page 9 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- overload::Method(obj,op)
- Returns undef or a reference to the method that
- implements op.
-
- OOOOvvvveeeerrrrllllooooaaaaddddiiiinnnngggg ccccoooonnnnssssttttaaaannnnttttssss
- For some application Perl parser mangles constants too much.
- It is possible to hook into this process via
- _o_v_e_r_l_o_a_d::_c_o_n_s_t_a_n_t() and _o_v_e_r_l_o_a_d::_r_e_m_o_v_e__c_o_n_s_t_a_n_t()
- functions.
-
- These functions take a hash as an argument. The recognized
- keys of this hash are
-
- integer to overload integer constants,
-
- float to overload floating point constants,
-
- binary to overload octal and hexadecimal constants,
-
- q to overload q-quoted strings, constant pieces of qq-
- and qx-quoted strings and here-documents,
-
- qr to overload constant pieces of regular expressions.
-
- The corresponding values are references to functions which
- take three arguments: the first one is the _i_n_i_t_i_a_l string
- form of the constant, the second one is how Perl interprets
- this constant, the third one is how the constant is used.
- Note that the initial string form does not contain string
- delimiters, and has backslashes in backslash-delimiter
- combinations stripped (thus the value of delimiter is not
- relevant for processing of this string). The return value
- of this function is how this constant is going to be
- interpreted by Perl. The third argument is undefined unless
- for overloaded q- and qr- constants, it is q in single-quote
- context (comes from strings, regular expressions, and
- single-quote HERE documents), it is tr for arguments of tr/y
- operators, it is s for right-hand side of s-operator, and it
- is qq otherwise.
-
- Since an expression "ab$cd,," is just a shortcut for 'ab' .
- $cd . ',,', it is expected that overloaded constant strings
- are equipped with reasonable overloaded catenation operator,
- otherwise absurd results will result. Similarly, negative
- numbers are considered as negations of positive constants.
-
- Note that it is probably meaningless to call the functions
- _o_v_e_r_l_o_a_d::_c_o_n_s_t_a_n_t() and _o_v_e_r_l_o_a_d::_r_e_m_o_v_e__c_o_n_s_t_a_n_t() from
- anywhere but _i_m_p_o_r_t() and _u_n_i_m_p_o_r_t() methods. From these
- methods they may be called as
-
-
-
-
-
- Page 10 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- sub import {
- shift;
- return unless @_;
- die "unknown import: @_" unless @_ == 1 and $_[0] eq ':constant';
- overload::constant integer => sub {Math::BigInt->new(shift)};
- }
-
- BBBBUUUUGGGGSSSS Currently overloaded-ness of constants does not
- propagate into eval '...'.
-
- IIIIMMMMPPPPLLLLEEEEMMMMEEEENNNNTTTTAAAATTTTIIIIOOOONNNN
- What follows is subject to change RSN.
-
- The table of methods for all operations is cached in magic
- for the symbol table hash for the package. The cache is
- invalidated during processing of use overload, no overload,
- new function definitions, and changes in @ISA. However, this
- invalidation remains unprocessed until the next blessing
- into the package. Hence if you want to change overloading
- structure dynamically, you'll need an additional (fake)
- blessing to update the table.
-
- (Every SVish thing has a magic queue, and magic is an entry
- in that queue. This is how a single variable may
- participate in multiple forms of magic simultaneously. For
- instance, environment variables regularly have two forms at
- once: their %ENV magic and their taint magic. However, the
- magic which implements overloading is applied to the
- stashes, which are rarely used directly, thus should not
- slow down Perl.)
-
- If an object belongs to a package using overload, it carries
- a special flag. Thus the only speed penalty during
- arithmetic operations without overloading is the checking of
- this flag.
-
- In fact, if use overload is not present, there is almost no
- overhead for overloadable operations, so most programs
- should not suffer measurable performance penalties. A
- considerable effort was made to minimize the overhead when
- overload is used in some package, but the arguments in
- question do not belong to packages using overload. When in
- doubt, test your speed with use overload and without it. So
- far there have been no reports of substantial speed
- degradation if Perl is compiled with optimization turned on.
-
- There is no size penalty for data if overload is not used.
- The only size penalty if overload is used in some package is
- that _a_l_l the packages acquire a magic during the next
- blessing into the package. This magic is three-words-long
- for packages without overloading, and carries the cache
- tabel if the package is overloaded.
-
-
-
- Page 11 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- Copying ($a=$b) is shallow; however, a one-level-deep
- copying is carried out before any operation that can imply
- an assignment to the object $a (or $b) refers to, like $a++.
- You can override this behavior by defining your own copy
- constructor (see the section on _C_o_p_y _C_o_n_s_t_r_u_c_t_o_r).
-
- It is expected that arguments to methods that are not
- explicitly supposed to be changed are constant (but this is
- not enforced).
-
- MMMMeeeettttaaaapppphhhhoooorrrr ccccllllaaaasssshhhh
- One may wonder why the semantic of overloaded = is so
- counterintuive. If it _l_o_o_k_s counterintuive to you, you are
- subject to a metaphor clash.
-
- Here is a Perl object metaphor:
-
- _o_b_j_e_c_t _i_s _a _r_e_f_e_r_e_n_c_e _t_o _b_l_e_s_s_e_d _d_a_t_a
-
- and an arithmetic metaphor:
-
- _o_b_j_e_c_t _i_s _a _t_h_i_n_g _b_y _i_t_s_e_l_f.
-
- The _m_a_i_n problem of overloading = is the fact that these
- metaphors imply different actions on the assignment $a = $b
- if $a and $b are objects. Perl-think implies that $a
- becomes a reference to whatever $b was referencing.
- Arithmetic-think implies that the value of "object" $a is
- changed to become the value of the object $b, preserving the
- fact that $a and $b are separate entities.
-
- The difference is not relevant in the absence of mutators.
- After a Perl-way assignment an operation which mutates the
- data referenced by $a would change the data referenced by $b
- too. Effectively, after $a = $b values of $a and $b become
- _i_n_d_i_s_t_i_n_g_u_i_s_h_a_b_l_e.
-
- On the other hand, anyone who has used algebraic notation
- knows the expressive power of the arithmetic metaphor.
- Overloading works hard to enable this metaphor while
- preserving the Perlian way as far as possible. Since it is
- not not possible to freely mix two contradicting metaphors,
- overloading allows the arithmetic way to write things _a_s _f_a_r
- _a_s _a_l_l _t_h_e _m_u_t_a_t_o_r_s _a_r_e _c_a_l_l_e_d _v_i_a _o_v_e_r_l_o_a_d_e_d _a_c_c_e_s_s _o_n_l_y.
- The way it is done is described in the section on _C_o_p_y
- _C_o_n_s_t_r_u_c_t_o_r.
-
- If some mutator methods are directly applied to the
- overloaded values, one may need to _e_x_p_l_i_c_i_t_l_y _u_n_l_i_n_k other
- values which references the same value:
-
-
-
-
-
- Page 12 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- $a = new Data 23;
- ...
- $b = $a; # $b is "linked" to $a
- ...
- $a = $a->clone; # Unlink $b from $a
- $a->increment_by(4);
-
- Note that overloaded access makes this transparent:
-
- $a = new Data 23;
- $b = $a; # $b is "linked" to $a
- $a += 4; # would unlink $b automagically
-
- However, it would not make
-
- $a = new Data 23;
- $a = 4; # Now $a is a plain 4, not 'Data'
-
- preserve "objectness" of $a. But Perl _h_a_s a way to make
- assignments to an object do whatever you want. It is just
- not the overload, but _t_i_e()ing interface (see the tie entry
- in the _p_e_r_l_f_u_n_c manpage). Adding a _F_E_T_C_H() method which
- returns the object itself, and _S_T_O_R_E() method which changes
- the value of the object, one can reproduce the arithmetic
- metaphor in its completeness, at least for variables which
- were _t_i_e()d from the start.
-
- (Note that a workaround for a bug may be needed, see the
- section on _B_U_G_S.)
-
- CCCCooooooookkkkbbbbooooooookkkk
- Please add examples to what follows!
-
- TTTTwwwwoooo----ffffaaaacccceeee ssssccccaaaallllaaaarrrrssss
-
- Put this in _t_w_o__f_a_c_e._p_m in your Perl library directory:
-
- package two_face; # Scalars with separate string and
- # numeric values.
- sub new { my $p = shift; bless [@_], $p }
- use overload '""' => \&str, '0+' => \&num, fallback => 1;
- sub num {shift->[1]}
- sub str {shift->[0]}
-
- Use it as follows:
-
- require two_face;
- my $seven = new two_face ("vii", 7);
- printf "seven=$seven, seven=%d, eight=%d\n", $seven, $seven+1;
- print "seven contains `i'\n" if $seven =~ /i/;
-
- (The second line creates a scalar which has both a string
-
-
-
- Page 13 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- value, and a numeric value.) This prints:
-
- seven=vii, seven=7, eight=8
- seven contains `i'
-
-
- SSSSyyyymmmmbbbboooolllliiiicccc ccccaaaallllccccuuuullllaaaattttoooorrrr
-
- Put this in _s_y_m_b_o_l_i_c._p_m in your Perl library directory:
-
- package symbolic; # Primitive symbolic calculator
- use overload nomethod => \&wrap;
-
- sub new { shift; bless ['n', @_] }
- sub wrap {
- my ($obj, $other, $inv, $meth) = @_;
- ($obj, $other) = ($other, $obj) if $inv;
- bless [$meth, $obj, $other];
- }
-
- This module is very unusual as overloaded modules go: it
- does not provide any usual overloaded operators, instead it
- provides the the section on _L_a_s_t _R_e_s_o_r_t operator nomethod.
- In this example the corresponding subroutine returns an
- object which encupsulates operations done over the objects:
- new symbolic 3 contains ['n', 3], 2 + new symbolic 3
- contains ['+', 2, ['n', 3]].
-
- Here is an example of the script which "calculates" the side
- of circumscribed octagon using the above package:
-
- require symbolic;
- my $iter = 1; # 2**($iter+2) = 8
- my $side = new symbolic 1;
- my $cnt = $iter;
-
- while ($cnt--) {
- $side = (sqrt(1 + $side**2) - 1)/$side;
- }
- print "OK\n";
-
- The value of $side is
-
- ['/', ['-', ['sqrt', ['+', 1, ['**', ['n', 1], 2]],
- undef], 1], ['n', 1]]
-
- Note that while we obtained this value using a nice little
- script, there is no simple way to _u_s_e this value. In fact
- this value may be inspected in debugger (see the _p_e_r_l_d_e_b_u_g
- manpage), but ony if bareStringify OOOOption is set, and not
- via p command.
-
-
-
-
- Page 14 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- If one attempts to print this value, then the overloaded
- operator "" will be called, which will call nomethod
- operator. The result of this operator will be stringified
- again, but this result is again of type symbolic, which will
- lead to an infinite loop.
-
- Add a pretty-printer method to the module _s_y_m_b_o_l_i_c._p_m:
-
- sub pretty {
- my ($meth, $a, $b) = @{+shift};
- $a = 'u' unless defined $a;
- $b = 'u' unless defined $b;
- $a = $a->pretty if ref $a;
- $b = $b->pretty if ref $b;
- "[$meth $a $b]";
- }
-
- Now one can finish the script by
-
- print "side = ", $side->pretty, "\n";
-
- The method pretty is doing object-to-string conversion, so
- it is natural to overload the operator "" using this method.
- However, inside such a method it is not necessary to
- pretty-print the _c_o_m_p_o_n_e_n_t_s $a and $b of an object. In the
- above subroutine "[$meth $a $b]" is a catenation of some
- strings and components $a and $b. If these components use
- overloading, the catenation operator will look for an
- overloaded operator ., if not present, it will look for an
- overloaded operator "". Thus it is enough to use
-
- use overload nomethod => \&wrap, '""' => \&str;
- sub str {
- my ($meth, $a, $b) = @{+shift};
- $a = 'u' unless defined $a;
- $b = 'u' unless defined $b;
- "[$meth $a $b]";
- }
-
- Now one can change the last line of the script to
-
- print "side = $side\n";
-
- which outputs
-
- side = [/ [- [sqrt [+ 1 [** [n 1 u] 2]] u] 1] [n 1 u]]
-
- and one can inspect the value in debugger using all the
- possible methods.
-
- Something is is still amiss: consider the loop variable $cnt
- of the script. It was a number, not an object. We cannot
-
-
-
- Page 15 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- make this value of type symbolic, since then the loop will
- not terminate.
-
- Indeed, to terminate the cycle, the $cnt should become
- false. However, the operator bool for checking falsity is
- overloaded (this time via overloaded ""), and returns a long
- string, thus any object of type symbolic is true. To
- overcome this, we need a way to compare an object to 0. In
- fact, it is easier to write a numeric conversion routine.
-
- Here is the text of _s_y_m_b_o_l_i_c._p_m with such a routine added
- (and slightly modifed _s_t_r()):
-
- package symbolic; # Primitive symbolic calculator
- use overload
- nomethod => \&wrap, '""' => \&str, '0+' => \#
-
- sub new { shift; bless ['n', @_] }
- sub wrap {
- my ($obj, $other, $inv, $meth) = @_;
- ($obj, $other) = ($other, $obj) if $inv;
- bless [$meth, $obj, $other];
- }
- sub str {
- my ($meth, $a, $b) = @{+shift};
- $a = 'u' unless defined $a;
- if (defined $b) {
- "[$meth $a $b]";
- } else {
- "[$meth $a]";
- }
- }
- my %subr = ( n => sub {$_[0]},
- sqrt => sub {sqrt $_[0]},
- '-' => sub {shift() - shift()},
- '+' => sub {shift() + shift()},
- '/' => sub {shift() / shift()},
- '*' => sub {shift() * shift()},
- '**' => sub {shift() ** shift()},
- );
- sub num {
- my ($meth, $a, $b) = @{+shift};
- my $subr = $subr{$meth}
- or die "Do not know how to ($meth) in symbolic";
- $a = $a->num if ref $a eq __PACKAGE__;
- $b = $b->num if ref $b eq __PACKAGE__;
- $subr->($a,$b);
- }
-
- All the work of numeric conversion is done in %subr and
- _n_u_m(). Of course, %subr is not complete, it contains only
- operators used in teh example below. Here is the extra-
-
-
-
- Page 16 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- credit question: why do we need an explicit recursion in
- _n_u_m()? (Answer is at the end of this section.)
-
- Use this module like this:
-
- require symbolic;
- my $iter = new symbolic 2; # 16-gon
- my $side = new symbolic 1;
- my $cnt = $iter;
-
- while ($cnt) {
- $cnt = $cnt - 1; # Mutator `--' not implemented
- $side = (sqrt(1 + $side**2) - 1)/$side;
- }
- printf "%s=%f\n", $side, $side;
- printf "pi=%f\n", $side*(2**($iter+2));
-
- It prints (without so many line breaks)
-
- [/ [- [sqrt [+ 1 [** [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1]
- [n 1]] 2]]] 1]
- [/ [- [sqrt [+ 1 [** [n 1] 2]]] 1] [n 1]]]=0.198912
- pi=3.182598
-
- The above module is very primitive. It does not implement
- mutator methods (++, -= and so on), does not do deep copying
- (not required without mutators!), and implements only those
- arithmetic operations which are used in the example.
-
- To implement most arithmetic operattions is easy, one should
- just use the tables of operations, and change the code which
- fills %subr to
-
- my %subr = ( 'n' => sub {$_[0]} );
- foreach my $op (split " ", $overload::ops{with_assign}) {
- $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
- }
- my @bins = qw(binary 3way_comparison num_comparison str_comparison);
- foreach my $op (split " ", "@overload::ops{ @bins }") {
- $subr{$op} = eval "sub {shift() $op shift()}";
- }
- foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
- print "defining `$op'\n";
- $subr{$op} = eval "sub {$op shift()}";
- }
-
- Due to the section on _C_a_l_l_i_n_g _C_o_n_v_e_n_t_i_o_n_s _f_o_r _M_u_t_a_t_o_r_s, we
- do not need anything special to make += and friends work,
- except filling += entry of %subr, and defining a copy
- constructor (needed since Perl has no way to know that the
- implementation of '+=' does not mutate the argument, compare
- the section on _C_o_p_y _C_o_n_s_t_r_u_c_t_o_r).
-
-
-
- Page 17 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- To implement a copy constructor, add '=' = \&cpy> to use
- overload line, and code (this code assumes that mutators
- change things one level deep only, so recursive copying is
- not needed):
-
- sub cpy {
- my $self = shift;
- bless [@$self], ref $self;
- }
-
- To make ++ and -- work, we need to implement actual
- mutators, either directly, or in nomethod. We continue to
- do things inside nomethod, thus add
-
- if ($meth eq '++' or $meth eq '--') {
- @$obj = ($meth, (bless [@$obj]), 1); # Avoid circular reference
- return $obj;
- }
-
- after the first line of _w_r_a_p(). This is not a most
- effective implementation, one may consider
-
- sub inc { $_[0] = bless ['++', shift, 1]; }
-
- instead.
-
- As a final remark, note that one can fill %subr by
-
- my %subr = ( 'n' => sub {$_[0]} );
- foreach my $op (split " ", $overload::ops{with_assign}) {
- $subr{$op} = $subr{"$op="} = eval "sub {shift() $op shift()}";
- }
- my @bins = qw(binary 3way_comparison num_comparison str_comparison);
- foreach my $op (split " ", "@overload::ops{ @bins }") {
- $subr{$op} = eval "sub {shift() $op shift()}";
- }
- foreach my $op (split " ", "@overload::ops{qw(unary func)}") {
- $subr{$op} = eval "sub {$op shift()}";
- }
- $subr{'++'} = $subr{'+'};
- $subr{'--'} = $subr{'-'};
-
- This finishes implementation of a primitive symbolic
- calculator in 50 lines of Perl code. Since the numeric
- values of subexpressions are not cached, the calculator is
- very slow.
-
- Here is the answer for the exercise: In the case of _s_t_r(),
- we need no explicit recursion since the overloaded
- .-operator will fall back to an existing overloaded operator
- "". Overloaded arithmetic operators _d_o _n_o_t fall back to
- numeric conversion if fallback is not explicitly requested.
-
-
-
- Page 18 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- Thus without an explicit recursion _n_u_m() would convert ['+',
- $a, $b] to $a + $b, which would just rebuild the argument of
- _n_u_m().
-
- If you wonder why defaults for conversion are different for
- _s_t_r() and _n_u_m(), note how easy it was to write the symbolic
- calculator. This simplicity is due to an appropriate choice
- of defaults. One extra note: due to teh explicit recursion
- _n_u_m() is more fragile than _s_y_m(): we need to explicitly
- check for the type of $a and $b. If componets $a and $b
- happen to be of some related type, this may lead to
- problems.
-
- _R_e_a_l_l_y symbolic calculator
-
- One may wonder why we call the above calculator symbolic.
- The reason is that the actual calculation of the value of
- expression is postponed until the value is _u_s_e_d.
-
- To see it in action, add a method
-
- sub STORE {
- my $obj = shift;
- $#$obj = 1;
- @$obj->[0,1] = ('=', shift);
- }
-
- to the package symbolic. After this change one can do
-
- my $a = new symbolic 3;
- my $b = new symbolic 4;
- my $c = sqrt($a**2 + $b**2);
-
- and the numeric value of $c becomes 5. However, after
- calling
-
- $a->STORE(12); $b->STORE(5);
-
- the numeric value of $c becomes 13. There is no doubt now
- that the module symbolic provides a _s_y_m_b_o_l_i_c calculator
- indeed.
-
- To hide the rough edges under the hood, provide a _t_i_e()d
- interface to the package symbolic (compare with the section
- on _M_e_t_a_p_h_o_r _c_l_a_s_h). Add methods
-
- sub TIESCALAR { my $pack = shift; $pack->new(@_) }
- sub FETCH { shift }
- sub nop { } # Around a bug
-
- (the bug is described in the section on _B_U_G_S). One can use
- this new interface as
-
-
-
- Page 19 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- tie $a, 'symbolic', 3;
- tie $b, 'symbolic', 4;
- $a->nop; $b->nop; # Around a bug
-
- my $c = sqrt($a**2 + $b**2);
-
- Now numeric value of $c is 5. After $a = 12; $b = 5 the
- numeric value of $c becomes 13. To insulate the user of the
- module add a method
-
- sub vars { my $p = shift; tie($_, $p), $_->nop foreach @_; }
-
- Now
-
- my ($a, $b);
- symbolic->vars($a, $b);
- my $c = sqrt($a**2 + $b**2);
-
- $a = 3; $b = 4;
- printf "c5 %s=%f\n", $c, $c;
-
- $a = 12; $b = 5;
- printf "c13 %s=%f\n", $c, $c;
-
- shows that the numeric value of $c follows changes to the
- values of $a and $b.
-
- AAAAUUUUTTTTHHHHOOOORRRR
- Ilya Zakharevich <_i_l_y_a@_m_a_t_h._m_p_s._o_h_i_o-_s_t_a_t_e._e_d_u>.
-
- DDDDIIIIAAAAGGGGNNNNOOOOSSSSTTTTIIIICCCCSSSS
- When Perl is run with the ----DDDDoooo switch or its equivalent,
- overloading induces diagnostic messages.
-
- Using the m command of Perl debugger (see the _p_e_r_l_d_e_b_u_g
- manpage) one can deduce which operations are overloaded (and
- which ancestor triggers this overloading). Say, if eq is
- overloaded, then the method (eq is shown by debugger. The
- method () corresponds to the fallback key (in fact a
- presence of this method shows that this package has
- overloading enabled, and it is what is used by the
- Overloaded function of module overload).
-
- BBBBUUUUGGGGSSSS
- Because it is used for overloading, the per-package hash
- %OVERLOAD now has a special meaning in Perl. The symbol
- table is filled with names looking like line-noise.
-
- For the purpose of inheritance every overloaded package
- behaves as if fallback is present (possibly undefined). This
- may create interesting effects if some package is not
- overloaded, but inherits from two overloaded packages.
-
-
-
- Page 20 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
- Relation between overloading and _t_i_e()ing is broken.
- Overloading is triggered or not basing on the _p_r_e_v_i_o_u_s class
- of _t_i_e()d value.
-
- This happens because the presence of overloading is checked
- too early, before any _t_i_e()d access is attempted. If the
- _F_E_T_C_H()ed class of the _t_i_e()d value does not change, a
- simple workaround is to access the value immediately after
- _t_i_e()ing, so that after this call the _p_r_e_v_i_o_u_s class
- coincides with the current one.
-
- NNNNeeeeeeeeddddeeeedddd:::: a way to fix this without a speed penalty.
-
- Barewords are not covered by overloaded string constants.
-
- This document is confusing. There are grammos and
- misleading language used in places. It would seem a total
- rewrite is needed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 21 (printed 10/23/98)
-
-
-
-
-
-
- oooovvvveeeerrrrllllooooaaaadddd((((3333)))) 1111////AAAAuuuugggg////99998888 ((((ppppeeeerrrrllll 5555....000000005555,,,, ppppaaaattttcccchhhh 00002222)))) oooovvvveeeerrrrllllooooaaaadddd((((3333))))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 22 (printed 10/23/98)
-
-
-
-
-
-
-